package mil.af.amc.adpetracker.dao.hibernate;

import mil.af.amc.adpetracker.dao.AdpeAccountDao;
import mil.af.amc.adpetracker.model.AdpeAccount;
import mil.af.amc.adpetracker.model.EquipmentItem;
import mil.af.amc.adpetracker.model.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Hibernate specific DAO implementation for ADPE Account objects
 *
 * @author TSgt Jason Ferguson
 */

public class HibernateAdpeAccountDao extends HibernateGenericDao<AdpeAccount> implements AdpeAccountDao {

    private static final Log log = LogFactory.getLog(HibernateAdpeAccountDao.class);

    public HibernateAdpeAccountDao() {
        super(AdpeAccount.class);
    }

    public HibernateAdpeAccountDao(Class<AdpeAccount> type) {
        super(type);
    }

    public int getEquipmentItemCount(AdpeAccount account) {

        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
        crit.setProjection(Projections.rowCount());
        crit.add(Restrictions.eq("account", account));
        return (Integer) getHibernateTemplate().findByCriteria(crit).get(0);

    }

    public double getAccountValue(final AdpeAccount account) {

        return (Double) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {

                Criteria crit = session.createCriteria(EquipmentItem.class);
                crit.add(Restrictions.eq("account", account));
                crit.setProjection(Projections.sum("originalCost"));
                crit.add(Restrictions.isNull("drmoPackage"));
                crit.add(Restrictions.isNull("rosPackage"));
                return crit.uniqueResult();

            }
        });

    }

    @SuppressWarnings({"unchecked"})
    public List<AdpeAccount> getAccountsByUser(final User user) {

        DetachedCriteria primaryCrit = DetachedCriteria.forClass(AdpeAccount.class);
        DetachedCriteria subCrit1 = primaryCrit.createCriteria("primaryCustodian");
        subCrit1.add(Restrictions.eq("id", user.getId()));

        List<AdpeAccount> list1 = (List<AdpeAccount>) getHibernateTemplate().findByCriteria(primaryCrit);

        DetachedCriteria altCrit = DetachedCriteria.forClass(AdpeAccount.class);
        DetachedCriteria subcrit2 = altCrit.createCriteria("alternateCustodians");
        subcrit2.add(Restrictions.eq("id", user.getId()));

        List<AdpeAccount> list2 = (List<AdpeAccount>) getHibernateTemplate().findByCriteria(altCrit);

        Set<AdpeAccount> transientSet = new HashSet<AdpeAccount>();
        transientSet.addAll(list1);
        transientSet.addAll(list2);

        List<AdpeAccount> resultList = new ArrayList<AdpeAccount>();
        resultList.addAll(transientSet);

        return resultList;

    }

}
